package bf.interpreter;

import bf.BFSyntaxError;

import java.io.*;
import java.util.ArrayDeque;
import java.util.Arrays;

/**
 * A simple Brainfuck interpreter
 *
 * @author Maxim Buzdalov
 */
public final class Interpreter {
    private final boolean supportPrintState;
    private final int memorySize;

    public Interpreter(int memorySize, boolean supportPrintState) {
        this.supportPrintState = supportPrintState;
        this.memorySize = memorySize;
    }

    public void run(String code, InputStream input, OutputStream output) throws IOException, BFSyntaxError {
        char[] c = filter(code, supportPrintState);
        byte[] state = new byte[memorySize];
        int[] jump = jumpTable(c);

        int p = 0;
        int m = 0;
        while (p < c.length) {
            switch (c[p]) {
                case '+': state[m]++; break;
                case '-': state[m]--; break;
                case '>': m = (m + 1) % memorySize; break;
                case '<': m = (m + memorySize - 1) % memorySize; break;
                case '[': p = (state[m] == 0 ? jump[p] : p); break;
                case ']': p = (state[m] == 0 ? p : jump[p]); break;
                case '.': output.write(state[m]); break;
                case ',': state[m] = (byte) (input.read()); break;
                case '#': {
                    System.err.println("mem: " + Arrays.toString(state));
                    System.err.println("ip: " + p);
                    System.err.println("mp: " + m);
                    break;
                }
            }
            ++p;
        }
    }

    private static int[] jumpTable(char[] c) throws BFSyntaxError {
        int[] jump = new int[c.length];
        ArrayDeque<Integer> stack = new ArrayDeque<Integer>();
        for (int i = 0; i < c.length; ++i) {
            if (c[i] == '[') {
                stack.addLast(i);
            } else if (c[i] == ']') {
                if (stack.isEmpty()) {
                    throw new BFSyntaxError("unmatched ]");
                }
                int last = stack.removeLast();
                jump[i] = last;
                jump[last] = i;
            }
        }
        if (!stack.isEmpty()) {
            throw new BFSyntaxError("unmatched [");
        }
        return jump;
    }

    private static char[] filter(String code, boolean supportPrintState) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < code.length(); ++i) {
            char c = code.charAt(i);
            if ("+-<>[].,".indexOf(c) >= 0 || c == '#' && supportPrintState) {
                sb.append(c);
            }
        }
        return sb.toString().toCharArray();
    }

    public static void main(String[] args) throws BFSyntaxError, IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder prog = new StringBuilder();
        String line;
        while ((line = in.readLine()).length() > 0) {
            prog.append(line);
        }
        new Interpreter(30000, true).run(prog.toString(), System.in, System.out);
        in.close();
        System.out.flush();
    }
}
